package iserver

import (
	"encoding/json"
	"src/zeus/common"
	"src/zeus/logger"
	"strings"

	"github.com/buguang01/util/flags"
	"github.com/spf13/viper"
)

// ServerInfo 服务器信息
type ServerInfo struct {
	Number       int32       `redis:"number"`   //线编号
	ServerID     uint64      `redis:"serverid"` //服务器ID 每个进程必须唯一,会写入etcd,会与-no组合 并非完全等同`FlagID`的
	Group        uint32      `redis:"group"`    //小区服ID
	Type         ServerType2 `redis:"type"`     //本服务器的类型
	InnerListen  string      `redis:"innerlisten"`
	InnerAddress string      `redis:"inneraddr"`
	OuterListen  string      `redis:"outerlisten"`
	OuterAddress string      `redis:"outeraddr"`
	HttpAddress  string      `redis:"httpaddr"`
	DebugAddress string      `redis:"dubugaddr"`
	Console      uint64      `redis:"console"`
	Load         int64       `redis:"load"` //负载
	Token        string      `redis:"token"`
	Status       int         `redis:"status"` //正常为0 灰度下线=-1
}

func (this *ServerInfo) String() string {
	result, _ := json.Marshal(this)
	return string(result)
}

// ServerList 服务器列表
type ServerList []*ServerInfo

// Len 实现Len方法
func (list ServerList) Len() int {
	return len(list)
}

// Swap 实现Swap方法
func (list ServerList) Swap(i, j int) {
	list[i], list[j] = list[j], list[i]
}

// Less 实现Less方法
func (list ServerList) Less(i, j int) bool {
	return list[i].Load < list[j].Load
}
func init() {
	flags.SetFlag(common.DockerIP, strings.ToUpper(common.DockerIP), "参数传递本机IP,会替换相互访问的IP", "")
	flags.SetFlag(common.DockerPost, strings.ToUpper(common.DockerPost), "参数传递对外端口,会替换ETCD中的对外端口", "0")
}

// 获取NewServer需要的参数
func GetServerBase(vmap *viper.Viper) (result *ServerBase) {
	// ip := flags.GetFlagByString(common.ServerIP)
	result = &ServerBase{
		Number:  int32(flags.GetFlagByInt(common.ServerNumber)),
		SrvID:   uint64(vmap.GetInt64("FlagId")) + uint64(flags.GetFlagByInt(common.ServerNumber)),
		GroupID: uint32(viper.GetInt("Config.GroupId")),
		FPS:     int(vmap.GetInt32("FPS")),
		Debug:   viper.GetBool("Config.Debug"),
		Recover: viper.GetBool("Config.Recover"),
	}
	//如果容器传入IP,则使用容器的外部IP作为服务IP DockerIp
	dockerIp := flags.GetFlagByString(common.DockerIP)

	if inner := vmap.GetStringMap("Inner"); inner != nil {
		vipport := viper.New()
		vipport.MergeConfigMap(inner)
		vipport.Unmarshal(&result.Inner)
		if dockerIp != "" {
			result.Inner.Addr = dockerIp
			logger.Info("已替换 Inner.Addr=", dockerIp)
		}
	}
	dockerpost := flags.GetFlagByInt(common.DockerPost)
	if outer := vmap.GetStringMap("Outer"); outer != nil {
		vipport := viper.New()
		vipport.MergeConfigMap(outer)
		vipport.Unmarshal(&result.Outer)
		if dockerpost != 0 {
			result.Outer.ParamPort = dockerpost
			logger.Info("已替换 Outer.ParamPort=", dockerpost)
		}
	}
	if htp := vmap.GetStringMap("Http"); htp != nil {
		vipport := viper.New()
		vipport.MergeConfigMap(htp)
		vipport.Unmarshal(&result.Httper)
		if dockerIp != "" {
			result.Httper.Addr = dockerIp
			logger.Info("已替换 Httper.Addr=", dockerIp)
		}
	}
	result.LocalType = make([]ServerType2, 0, 10)
	stringList := vmap.GetIntSlice("LocalType")
	for _, v := range stringList {
		result.LocalType = append(result.LocalType, ServerType2(v))
	}
	result.WatchLocalTypes = make([]ServerType2, 0, 10)
	stringList = vmap.GetIntSlice("WatchLocalTypes")
	for _, v := range stringList {
		result.WatchLocalTypes = append(result.WatchLocalTypes, ServerType2(v))
	}
	result.GlobalType = make([]ServerType2, 0, 10)
	stringList = vmap.GetIntSlice("GlobalType")
	for _, v := range stringList {
		result.GlobalType = append(result.GlobalType, ServerType2(v))
	}

	return
}

type ServerBase struct {
	SrvID           uint64
	Number          int32         //服务器线号（大场景分线的时候，需要使用）
	GroupID         uint32        //本服务器组ID
	FPS             int           //针数
	Debug           bool          //是否调试
	Recover         bool          //是否Recover
	Inner           PortInfo      //服务器之间的
	Outer           PortInfo      //对外的
	Httper          PortInfo      //http请求的
	LocalType       []ServerType2 //主动连接的服务器类型
	WatchLocalTypes []ServerType2 //关注的本区的服务器类型
	Ogroupid        uint32        //对应跨服组ID
	GlobalType      []ServerType2 //主动连接的全局服务器类型
}

func (this *ServerBase) String() string {
	result, _ := json.Marshal(this)
	return string(result)
}

type PortInfo struct {
	Addr      string
	Listen    string
	PortMin   int
	PortMax   int
	MaxConns  int
	ParamPort int
}

const (
	SERVER_STATUS_OK     = 0
	SERVER_STATUS_FORBID = -1
)
